package top.chendawei.system.service.impl;

import com.google.common.collect.Sets;
import org.apache.commons.collections.CollectionUtils;
import org.hibernate.query.Query;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import top.chendawei.aop.localcache.GuavaLocalCache;
import top.chendawei.system.beans.entity.SysAuth;
import top.chendawei.system.beans.entity.SysRole;
import top.chendawei.system.beans.entity.SysRoleAuth;
import top.chendawei.system.dao.HibernateDaoSupport;
import top.chendawei.system.service.ICommonService;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

@Service
public class AuthServiceImpl extends HibernateDaoSupport {

    @Autowired
    private ICommonService commonService;

    @GuavaLocalCache(keyExt = "#plat", expireTime = 60 * 60 * 24, refreshTime = 60)
    public List<SysAuth> queryAllAuthRoteList(int plat) {
        String hql = "from SysAuth  where plat=:plat and type=0";
        Query query = getCurrentSession().createQuery(hql);
        query.setParameter("plat", plat);
        List<SysAuth> ll = query.list();
        if (CollectionUtils.isNotEmpty(ll)) {
            return list2TreeList(ll);
        }
        return Collections.emptyList();
    }

    private List<SysAuth> list2TreeList(List<SysAuth> ll) {
        Map<Long, List<SysAuth>> authByPIdMap = ll.stream().collect(Collectors.groupingBy(SysAuth::getPid));
        ll.forEach(x -> {
            List<SysAuth> sub = authByPIdMap.get(x.getId());
            x.setSubAuth(sub);
        });
        return ll.stream().filter(v -> v.getPid().equals(0L)).collect(Collectors.toList());
    }

    public List<SysRoleAuth> querySysRoleAuthList(Collection<Long> roleIds, Integer checked) {
        StringBuilder hql = new StringBuilder("from SysRoleAuth  where roleId in (:roleIds) ");
        if (null != checked) {
            hql.append(" and checked=:checked");
        }
        Query query = getCurrentSession().createQuery(hql.toString());
        query.setParameter("roleIds", roleIds);
        if (null != checked) {
            query.setParameter("checked", checked);
        }
        List<SysRoleAuth> ll = query.list();
        return ll;
    }

    @GuavaLocalCache(keyExt = "#roleIds", expireTime = 60 * 10, refreshTime = 60)
    public Set<Long> queryAuthIdList(List<Long> roleIds) {
        if (CollectionUtils.isEmpty(roleIds)) {
            return Sets.newHashSet();
        }
        List<SysRoleAuth> ll = querySysRoleAuthList(roleIds, null);
        return ll.stream().map(x -> x.getAuthId()).collect(Collectors.toSet());
    }

    public Set<Long> queryCheckedAuthIdList(Collection<Long> roleIds) {
        List<SysRoleAuth> ll = querySysRoleAuthList(roleIds, 1);
        return ll.stream().map(x -> x.getAuthId()).collect(Collectors.toSet());
    }


    //    @GuavaLocalCache(keyExt = "'all_'+#plat", expireTime = 60 * 60 * 24, refreshTime = 60 * 60 * 12)
    public List<SysAuth> queryAllAuthList(int plat) {
        List<SysAuth> ll = doQueryAllAuthList(plat);
        if (CollectionUtils.isNotEmpty(ll)) {
            return list2TreeList(ll);
        }
        return Collections.emptyList();
    }

    private List<SysAuth> doQueryAllAuthList(int plat) {
        String hql = "from SysAuth  where plat=:plat ";
        Query query = getCurrentSession().createQuery(hql);
        query.setParameter("plat", plat);
        List<SysAuth> ll = query.list();
        return ll;
    }

    public void deleteSysRoleAuthByRoleId(Long roleId) {
        String hql = "from SysRoleAuth where roleId=:roleId";
        Query query = getCurrentSession().createQuery(hql);
        query.setParameter("roleId", roleId);
        List list = query.list();
        Iterator it = list.iterator();
        while (it.hasNext()) {
            SysRoleAuth uf = (SysRoleAuth) it.next();  //获取一个对象
            getCurrentSession().delete(uf);  //删除指定对象
        }
    }

    public void batchSaveRoleAuth(Set<Long> checkedKeys, SysRole r, Integer plat) {
        if (CollectionUtils.isEmpty(checkedKeys)) {
            return;
        }
        List<SysAuth> ll = doQueryAllAuthList(plat);
        if (CollectionUtils.isNotEmpty(ll)) {
            Map<Long, Long> child2PMap = ll.stream().collect(Collectors.toMap(x -> x.getId(), x -> x.getPid(), (k1, k2) -> k1));
            //半选中的id
            Set<Long> checkedp = collectPCheck(child2PMap, checkedKeys);
            List<SysRoleAuth> lll = new ArrayList<>();
            if (CollectionUtils.isNotEmpty(checkedp)) {
                checkedp.forEach(x -> {
                    SysRoleAuth ra = SysRoleAuth.builder().authId(x).roleId(r.getId()).checked(0).build();
                    lll.add(ra);
                });
            }
            checkedKeys.forEach(x -> {
                SysRoleAuth ra = SysRoleAuth.builder().authId(x).roleId(r.getId()).checked(1).build();
                lll.add(ra);
            });
            commonService.commonBatchAdd(lll);
        }
    }

    private Set<Long> collectPCheck(Map<Long, Long> child2PMap, Set<Long> checkedKeys) {
        Set<Long> newAdd = new HashSet<>();
        checkedKeys.forEach(x -> {
            doCollectParent(x, newAdd, child2PMap, checkedKeys);

        });
        return newAdd;
    }

    private void doCollectParent(Long x, Set<Long> newAdd, Map<Long, Long> child2PMap, Set<Long> checkedKeys) {
        Long pid = child2PMap.get(x);
        if (null != pid) {
            if (!checkedKeys.contains(pid)) {
                newAdd.add(pid);
            }
            doCollectParent(pid, newAdd, child2PMap, checkedKeys);
        }
    }
}
